# -*- coding: utf-8 -*-
# @Time    : 2024/6/11 14:45
# @Author  : yujiahao
# @File    : 12_coding_attention.py
# @description: 数据类型补充说明

'''
最后我们对我们学习的这些数据类型进行一个总结,我们按照有序,无序,可变,不可变,取值方式来总结:

    有序:
        数字
        字符串
        列表
        元组
    无序:
        字典
        集合
    可变数据类型:
        列表
        字典
        集合
    不可变数据类型:
        字符串
        数字
        元组
    取值顺序:
        直接取值 — 数字,布尔值,集合
        顺序取值(可以索引) — 列表,元组,字符串
        通过键取值 — 字典

'''

#  todo 1、dict

# 1、 随机删除

dic = {"key":"value","key2":"value2"}
dic.popitem()  # 随机删除

# 2、批量创建字典
'''
formkeys这个是个坑,坑点就在于值是可变数据类型的时候,当第一个键对应的值进行修改了以后,其余的键对应的值也都跟着进行改变了. 如何避免坑,就是批量创建字典的时候值不能使用可变的数据类型.

在批量创建字典时，如果值是可变的数据类型（如列表、字典），需要确保每个键都有一个独立的对象。可以使用字典推导式或循环来实现这一点，从而避免共享同一个对象带来的副作用。
'''

dic = {}
dic1 = dic.fromkeys("abc", [1, 2])
print(dic1)  # 输出: {'a': [1, 2], 'b': [1, 2], 'c': [1, 2]}

# 修改其中一个键的值
dic1['a'].append(3)
print(dic1)  # 输出: {'a': [1, 2, 3], 'b': [1, 2, 3], 'c': [1, 2, 3]}


# 避免这个问题的方法
# 为了避免这个问题，可以在创建字典时确保每个键都有一个独立的对象。可以使用字典推导式来实现这一点。

# ① 使用字典推导式创建独立的列表对象

''' 在这个例子中，每个键都有一个独立的列表对象，因此修改 dic1['a'] 不会影响 dic1['b'] 和 dic1['c'] '''
keys = "abc"
dic1 = {key: [1, 2] for key in keys}
print(dic1)  # 输出: {'a': [1, 2], 'b': [1, 2], 'c': [1, 2]}

# 修改其中一个键的值
dic1['a'].append(3)
print(dic1)  # 输出: {'a': [1, 2, 3], 'b': [1, 2], 'c': [1, 2]}


# ② 使用循环创建独立的对象


# 使用循环创建独立的列表对象
keys = "abc"
dic1 = {}
for key in keys:
    dic1[key] = [1, 2]

print(dic1)  # 输出: {'a': [1, 2], 'b': [1, 2], 'c': [1, 2]}

# 修改其中一个键的值
dic1['a'].append(3)
print(dic1)  # 输出: {'a': [1, 2, 3], 'b': [1, 2], 'c': [1, 2]}

# 通过上述方法，我们可以确保每个键都有一个独立的对象，从而避免了修改一个键的值会影响其他键的值的问题。


print('''\n-----------------------------------☆☆☆分割线☆☆☆----------------------------------------\n''')



# todo 2、类型转换

'''
    元组 => 列表 list(tuple)

　　 列表 => 元组 tuple(list)

　　 list=>str str.join(list)

　　 str=>list str.split()

　　 转换成False的数据: 0,'',None,[],(),{},set() ==> False
'''

# todo 3、以后要遇到的坑


# 3.1 循环添加

lst = [1,2,3,4,5,6]
lst.append(7)

# 这样写法就会一直持续添加7
# for i in lst:
#     lst.append(7)
#     print(lst)
print(lst)


# 3.2 列表循环删除
# 列表: 循环删除列表中的每⼀个元素

li = [11, 22, 33, 44]


for e in li:
 li.remove(e)
print(li)



''' 
# 结果:
# [22, 44]
# 分析原因: for的运⾏过程. 会有⼀个指针来记录当前循环的元素是哪⼀个, ⼀开始这个指针指向第0 个.
# 然后获取到第0个元素. 紧接着删除第0个. 这个时候. 原来是第⼀个的元素会⾃动的变成 第0个.
# 然后指针向后移动⼀次, 指向1元素. 这时原来的1已经变成了0, 也就不会被删除了.'''


li = [11, 22, 33, 44]

for i in range(0, len(li)):
    try:
     del li[i]
    except :
        print(f'忽略此条报错')
print(li)

# 结果: 报错
# i= 0, 1, 2 删除的时候li[0] 被删除之后. 后⾯⼀个就变成了第0个.
# 以此类推. 当i = 2的时候. list中只有⼀个元素. 但是这个时候删除的是第2个 肯定报错啊
# 经过分析发现. 循环删除都不⾏. 不论是⽤del还是⽤remove. 都不能实现. 那么pop呢?

# pop删除试试看:
for el in li:
 li.pop() # pop也不⾏
print(li)
# 结果:
# [11, 22]


# todo 3.3 列表循环删除成功
# 只有这样才是可以的:

for i in range(0, len(li)): # 循环len(li)次, 然后从后往前删除
 li.pop()
print(li)
# 或者. ⽤另⼀个列表来记录你要删除的内容. 然后循环删除

li = [11, 22, 33, 44]
del_li = []
for e in li:
 del_li.append(e)
for e in del_li:
 li.remove(e)

print(li)
''' 注意: 由于删除元素会导致元素的索引改变, 所以容易出现问题. 尽量不要再循环中直接去删 除元素. 可以把要删除的元素添加到另⼀个集合中然后再批量删除'''

print('''\n-----------------------------------☆☆☆分割线☆☆☆----------------------------------------\n''')



# todo 3.4 字典的坑
# dict中的fromkey(),再次重提 可以帮我们通过list来创建⼀个dict

dic = dict.fromkeys(["jay", "JJ"], ["周杰伦", "麻花藤"])
print(dic)
# 结果:
# {'jay': ['周杰伦', '麻花藤'], 'JJ': ['周杰伦', '麻花藤']}
# 代码中只是更改了jay那个列表. 但是由于jay和JJ⽤的是同⼀个列表. 所以. 前⾯那个改了. 后面那个也会跟着改　



print('''\n-----------------------------------☆☆☆分割线☆☆☆----------------------------------------\n''')

# todo 3.5 字典在循环时不能修改

# dict中的元素在迭代过程中是不允许进⾏删除的

dic = {'k1': '🧽👶🏻', 'k2': '🐙哥', 's1': '🦀⽼板'}
# 删除key中带有'k'的元素
try:
    for k in dic:
      if 'k' in k:
          del dic[k] # dictionary changed size during iteration, 在循环迭代的时候不允许进⾏删除操作
except:
    print('忽略报错')
print(dic)
# 那怎么办呢? 把要删除的元素暂时先保存在⼀个list中, 然后循环list, 再删除

dic = {'k1': '🧽👶🏻', 'k2': '🐙哥', 's1': '🦀⽼板'}
dic_del_list = []
# 删除key中带有'k'的元素
for k in dic:
    if 'k' in k:
        dic_del_list.append(k)
for el in dic_del_list:
    del dic[el]
print(dic)

